package com.jysz.certificate.web.action.pm;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import ognl.Ognl;
import ognl.OgnlException;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.jysz.certificate.action.AbstractBaseAction;
import com.jysz.certificate.constant.OperCodeConstant;
import com.jysz.certificate.persistence.model.mf.BillOption;
import com.jysz.certificate.persistence.model.pm.PmUserList;
import com.jysz.certificate.persistence.model.system.Brand;
import com.jysz.certificate.persistence.model.system.Financial;
import com.jysz.certificate.persistence.model.system.Organization;
import com.jysz.certificate.persistence.model.system.Shop;
import com.jysz.certificate.persistence.model.system.User;
import com.jysz.certificate.service.cm.CertificationService;
import com.jysz.certificate.service.mf.BillOptionService;
import com.jysz.certificate.service.mf.BillService;
import com.jysz.certificate.service.pm.PmUserListService;
import com.jysz.certificate.service.system.BrandService;
import com.jysz.certificate.service.system.FinancialService;
import com.jysz.certificate.utils.PoiUtils;
import com.jysz.webcore.ssh.annotation.PermissionPoint;
import com.jysz.webcore.utils.ReflectionUtils;

/**
 * @author <a href="mailto:javaengine@outlook.com">Kaca Rich</a>
 * 
 */
@Controller
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Namespace("/pm")
public class PerformanceAction extends AbstractBaseAction {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private Long financialId;
	private String payMonth;
	private List<Financial> financials;

	@Resource
	private FinancialService financialService;
	@Resource
	private BillService billService;
	@Resource
	private BillOptionService billOptionService;
	@Resource
	private CertificationService certificationService;

	@Resource
	private BrandService brandService;
	
	@Resource
	private PmUserListService pmUserListService;
	
	@PermissionPoint(point = OperCodeConstant.M_PM_EXPORT)
	@Action("exportShopsInfoIndex")
	public String exportShopsInfoIndex() {
		financials = financialService.findAvailableAll();
		return "exportShopsInfoIndex";
	}

	
	public String getArearStr(Shop shop){
		List<Organization> areaOrgUsers = shop.getArea().getStaffChilds();
		if(areaOrgUsers != null && areaOrgUsers.size() > 0){
			return ReflectionUtils.convertElementPropertyToString(areaOrgUsers, "name", ",");
		}
		return "";
	}
	
	public String getShoperStr(Shop shop, String monthDate){
		List<PmUserList> pmUserLists = pmUserListService.findByMonthDate(monthDate, shop);
		if(pmUserLists != null && pmUserLists.size() > 0){
			List<User> users = pmUserLists.get(0).getUsers();
			return users != null ? ReflectionUtils.convertElementPropertyToString(users, "realName", ",") : "";
		}
		
		return "";
	}
	@SuppressWarnings("unchecked")
	@Action("exportShopsInfo")
	public String exportShopsInfo() {
		OutputStream out = null;
		try {
			out = this.getResponse().getOutputStream();
		} catch (IOException e) {
			LOG.error("导出绩效出错。。。", e);
		}
		Financial financial = financialService.find(this.getFinancialId());
		HttpServletResponse response = this.getResponse();
		response.setContentType("octets/stream");
		response.addHeader("Content-Disposition", "attachment;filename="
				+ toUtf8Encode(financial.getName() + "绩效导出_") + this.getPayMonth() + ".xls");

		List<String> months = billOptionService.findPayExportMonths(
				financialId, payMonth);
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = PoiUtils
				.createSheet(this.getPayMonth(), workbook);
		if (months != null && months.size() > 0) {

			int rowIndex = 0;

			Map<String, Object> context = new HashMap<String, Object>();
			context.put("pme", this);
			String[] headerStarts = { "序号", "店号", "店名", "驻店顾问", "区域经理" };
			String[] headerEnds = { "管理费(元)", "备注" };
			String[] columnHeaders = { "#index", "shop.shopMark",
					"shop.shopName",  "#pme.getShoperStr(shop, month)", "#pme.getArearStr(shop)" };
			String[] columnEnds = { "amount", "remark" };

			HSSFCellStyle headerStyle = PoiUtils.createHeaderStyle(workbook);
			HSSFCellStyle headerMonthStyle = PoiUtils
					.createHeaderStyle(workbook);
			headerMonthStyle.setFillForegroundColor(HSSFColor.WHITE.index);
			HSSFCellStyle contentStyle = PoiUtils
					.createContentCellStyle(workbook);

			List<Brand> brands = brandService.findAll();
			List<String> headers = new ArrayList<String>();
			headers.addAll(Arrays.asList(headerStarts));
			if (brands != null && brands.size() > 0) {
				List<String> brandNames = ReflectionUtils
						.convertElementPropertyToList(brands, "name");
				headers.addAll(brandNames);
				headers.addAll(brandNames);
			}
			headers.addAll(Arrays.asList(headerEnds));

			for (Iterator<String> iterator = months.iterator(); iterator
					.hasNext();) {
				String month = iterator.next();
				List<BillOption> shops = billOptionService.findShopsAtPayMonth(
						financialId, payMonth, month);
				if (shops == null || shops.size() < 1) {
					continue;
				}

				List<Shop> shopList = (List<Shop>) ReflectionUtils
						.convertElementPropertyToList(shops,
								"shop");
				List<Object[]> currentMonthQtys = certificationService
						.findCountCurrentMonth(this.getFinancialId(), month,
								shopList);
				List<Object[]> preMonthQtys = certificationService
						.findCountPreMonth(this.getFinancialId(), month,
								shopList);
//				List<PmUserList> pmUserLists = pmUserListService.findByMonthDate(month, shopList);
				Map<Long, Map<Long, Long>> currentMonthQtyMap = this
						.convertToMap(currentMonthQtys);
				Map<Long, Map<Long, Long>> preMonthQtyMap = this
						.convertToMap(preMonthQtys);
				context.put("currentMonthQtyMap", currentMonthQtyMap);
				context.put("preMonthQtyMap", preMonthQtyMap);

				List<String> columnList = this.converToOgnlExpresss(
						columnHeaders, brands, "currentMonthQtyMap",
						"preMonthQtyMap");

				columnList.addAll(Arrays.asList(columnEnds));

				Object[] columns = columnList.toArray();

				// 产生表格标题行
				HSSFRow row = sheet.createRow(rowIndex);

				HSSFCell cell = row.createCell(0);
				
				HSSFRichTextString text = new HSSFRichTextString(month
						+ "月份管理费明细");

				cell.setCellValue(text);
				
				CellRangeAddress region = new CellRangeAddress(rowIndex, rowIndex,
						0, headerStarts.length - 1);
				sheet.addMergedRegion(region);
				PoiUtils.setRegionStyle(sheet, region, headerMonthStyle);
				cell.setCellStyle(headerMonthStyle);

				//当月库存
				cell = row.createCell(headerStarts.length);
				text = new HSSFRichTextString("当月入库");
				cell.setCellValue(text);
				region = new CellRangeAddress(rowIndex, rowIndex,
						headerStarts.length, headerStarts.length + brands.size() - 1);
				sheet.addMergedRegion(region);
				PoiUtils.setRegionStyle(sheet, region, headerMonthStyle);
				cell.setCellStyle(headerMonthStyle);
				
				//上月结存
				cell = row.createCell(headerStarts.length + brands.size());
				text = new HSSFRichTextString("上月结存");
				cell.setCellValue(text);
				region = new CellRangeAddress(rowIndex, rowIndex,
						headerStarts.length + brands.size(), headerStarts.length + brands.size()*2 - 1);
				sheet.addMergedRegion(region);
				PoiUtils.setRegionStyle(sheet, region, headerMonthStyle);
				cell.setCellStyle(headerMonthStyle);
				
				//尾部
				cell = row.createCell(headerStarts.length + brands.size()*2);
				text = new HSSFRichTextString("");
				cell.setCellValue(text);
				region = new CellRangeAddress(rowIndex, rowIndex,
						headerStarts.length + brands.size()*2, headers.size() - 1);
				sheet.addMergedRegion(region);
				PoiUtils.setRegionStyle(sheet, region, headerMonthStyle);
				cell.setCellStyle(headerMonthStyle);
				row = sheet.createRow(++rowIndex);
				this.generatorHeaders(row, headerStyle, headers.toArray());

				rowIndex++;

				int index = 0;

				for (Iterator<BillOption> shopIterator = shops.iterator(); shopIterator
						.hasNext();) {

					index++;
					BillOption shop = shopIterator.next();

					row = sheet.createRow(rowIndex);
					context.put("index", index);
					for (int i = 0; i < columns.length; i++) {
						cell = row.createCell(i);
						cell.setCellStyle(contentStyle);

						Object obj = null;
						try {
							if(shop.getShop().getId()==9){
								obj = Ognl.getValue(columns[i].toString(), context,
										shop);
							}else{
								obj = Ognl.getValue(columns[i].toString(), context,
										shop);
							} 

						} catch (OgnlException e) {
							LOG.error("OGNL表达式错误。", e);
						}

						String textValue = obj != null ? obj.toString() : "";

						if (textValue != null) {
//							if (NumberUtils.isNumber(textValue)) {
								// 是数字当作double处理
//								cell.setCellValue(NumberUtils
//										.toDouble(textValue));
//							} else {
								HSSFRichTextString richString = new HSSFRichTextString(
										textValue);
								HSSFFont font3 = PoiUtils
										.createTextFont(workbook);
								richString.applyFont(font3);
								cell.setCellValue(richString);
//							}
						}

					}

					rowIndex++;
					
				}
				
				rowIndex++;
				rowIndex++;
				rowIndex++;
			}

		}
		try {
			workbook.write(out);
			out.close();
		} catch (IOException e) {
			LOG.error("导出绩效出错。。。", e);
		}
		return null;
	}

	@SuppressWarnings("deprecation")
	public void generatorHeaders(HSSFRow row, HSSFCellStyle headerStyle,
			Object[] headers) {

		for (short i = 0; i < headers.length; i++) {
			HSSFCell cell = row.createCell(i);
			cell.setCellStyle(headerStyle);
			HSSFRichTextString text = new HSSFRichTextString(
					headers[i].toString());
			cell.setCellValue(text);
		}
	}

	private final String OGNL_SHOP = "shop";

	private List<String> converToOgnlExpresss(String[] columnHeaders,
			List<Brand> brands, String currentMonthQtyMap, String preMonthQtyMap) {
		List<String> columnList = new ArrayList<String>();

		columnList.addAll(Arrays.asList(columnHeaders));
		if (brands != null && brands.size() > 0) {
			for (Iterator<Brand> iterator2 = brands.iterator(); iterator2
					.hasNext();) {
				Brand brand = iterator2.next();

				columnList.add("#" + currentMonthQtyMap + "[new Long(" + OGNL_SHOP + ".id"
						+ ")] == null ? null :" + "#" + currentMonthQtyMap + "[new Long(" + OGNL_SHOP + ".id"
								+ ")][new Long("
						+ brand.getId() + ")]");
			}
//			"#preMonthQtyMap[new Long(shop.id)].get(new Long(2))"
			for (Iterator<Brand> iterator2 = brands.iterator(); iterator2
					.hasNext();) { 
				Brand brand = iterator2.next();

				columnList.add("#" + preMonthQtyMap + "[new Long(" + OGNL_SHOP + ".id" + ")] == null ? null : " + "#" + preMonthQtyMap + "[new Long(" + OGNL_SHOP + ".id" + ")][new Long("
						+ brand.getId() + ")]");
			}
		}
		return columnList;
	}

	/**
	 * @param currentMonthQtys
	 * @return
	 */
	private Map<Long, Map<Long, Long>> convertToMap(List<Object[]> monthQtys) {
		Map<Long, Map<Long, Long>> map = new HashMap<Long, Map<Long, Long>>();

		if (monthQtys != null && monthQtys.size() > 0) {
			for (Iterator<Object[]> iterator = monthQtys.iterator(); iterator
					.hasNext();) {
				Object[] object = iterator.next();
				Map<Long, Long> brandMap = null;
				Long shopId = ((Shop)object[1]).getId();
				Long brandId = ((Brand)object[2]).getId();

				if (!map.containsKey(shopId)) {
					brandMap = new HashMap<Long, Long>();

					map.put(shopId, brandMap);
				} else {
					brandMap = map.get(shopId);
				}

				brandMap.put(brandId, Long.valueOf(object[0].toString()));
			}
		}

		return map;
	}

	public Long getFinancialId() {
		return financialId;
	}

	public void setFinancialId(Long financialId) {
		this.financialId = financialId;
	}

	public String getPayMonth() {
		return payMonth;
	}

	public void setPayMonth(String payMonth) {
		this.payMonth = payMonth;
	}

	public List<Financial> getFinancials() {
		return financials;
	}

	public void setFinancials(List<Financial> financials) {
		this.financials = financials;
	}

}
